package tc.crase.cmds;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Vector;

import javax.swing.AbstractButton;
import javax.swing.Box;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JTextField;

import tc.common.registry.RegistrySys;
import tc.common.utility.GrView;
import tc.common.utility.Pair;
import tc.common.utility.TcCmd;
import tc.common.utility.TcDisplayTransf;
import tc.crase.db.Xattr;
import tc.crase.db.XattrLNK;
import tc.crase.db.XattrSTR;
import tc.crase.db.XattrTPE;
import tc.crase.db.XattrURL;
import tc.crase.db.Xdb;
import tc.crase.meta.LinkEstimate;
import tc.crase.sys.XdbEx;
import tc.crase.sys.XobjectEx;

public class CmdMerge  extends CmdEx  implements ActionListener {
	JLabel object1Label;
	JLabel object2Label;
		
	JButton cleanButton;
	JButton mergeButton;
	
	public XobjectEx xoFirst() {
		if (Selection.selset.size() < 1) return null;
		return (XobjectEx)Selection.selset.get(0);
	}
	
	public XobjectEx xoSecond() {
		if (Selection.selset.size() < 2) return null;
		return (XobjectEx)Selection.selset.get(1);
	}
	
	public CmdMerge () {
	}
	
	private void update() {
		object1Label.setText("<html><b>not selected</b></html>");
		object2Label.setText("<html><b>not selected</b></html>");
		
		if (xoFirst() != null)  {
			XobjectEx obj1 = xoFirst();
			object1Label.setText("<html>" + obj1.formatTypes() + ": <b>" + obj1.getName() + "</b></html>");
		}
		
		if (xoSecond() != null)  {
			XobjectEx obj2 = xoSecond();
			object2Label.setText("<html>" + obj2.formatTypes() + ": <b>" + obj2.getName() + "</b></html>");
		}
		
		if ( (xoFirst() != null) || (xoSecond() !=null )) {
			cleanButton.setEnabled(true);
		}
		else
		{	cleanButton.setEnabled(false);
		}
		
		if (xoFirst() == null) setHint("Select first object.");
		else if (xoSecond() == null) setHint("Select secondObject.");
		else setHint("Click button <b>Create</b> to merge objects.");  

	}
	
	public void initializeDialog() {
		super.initializeDialog();
		setLabel("Link");
		hint.setText("Enter point.");
		
		Selection.objectsAllowed = true;
		
		object1Label = new JLabel();
		object2Label = new JLabel();
		
		cleanButton = new JButton("Clean");
		cleanButton.addActionListener(this);
		cleanButton.setActionCommand("clean");
		cleanButton.setMaximumSize(new Dimension(80,24));
		cleanButton.setPreferredSize(new Dimension(80,24));

		mergeButton = new JButton("Merge");
		mergeButton.addActionListener(this);
		mergeButton.setActionCommand("merge");
		mergeButton.setPreferredSize(new Dimension(SIDEBAR_WIDTH,32));
		mergeButton.setMaximumSize(new Dimension(SIDEBAR_WIDTH,32));

		dialog.add(object1Label);
		dialog.add(Box.createRigidArea(new Dimension(0,3)));
		Box box = Box.createHorizontalBox();
		dialog.add(box);
				
		dialog.add(Box.createRigidArea(new Dimension(0,10)));
				
		dialog.add(object2Label);
		dialog.add(Box.createRigidArea(new Dimension(0,3)));
		box = Box.createHorizontalBox();
		dialog.add(box);
		
		dialog.add(Box.createRigidArea(new Dimension(0,20)));
		dialog.add(cleanButton);
		dialog.add(Box.createRigidArea(new Dimension(0,50)));
		dialog.add(mergeButton);
		
		finalizeDialog();
		
		update();
		
		Selection.objectsAllowed = true;
	}
	
	public void enterSelected(Point pt, GrView view, Object object) {
		if (xoFirst() == null) {
			if (object instanceof XobjectEx == false) return;
			RegistrySys.registry.lock(); {
				Selection.add((XobjectEx)object);
			} RegistrySys.registry.unlock();
		}
		else if (xoSecond() == null) {
			if (object instanceof XobjectEx == false) return;
			XobjectEx second = (XobjectEx)object; 
			
			Xdb db = xoFirst().getDb();
			if (db != second.getDb()) {
				return;
			}
			
			RegistrySys.registry.lock(); {
				Selection.add(second);
			} RegistrySys.registry.unlock();	
		}
		
		update();
	}
	
	public void enterReset(GrView view) {
	}
	public void enterMove(Point pt, GrView view)  {
	}
	
	private void draw(Graphics g, TcDisplayTransf transf, Color background)
	{
	}
	
	private void merge() { //TODO Should be method
		XobjectEx xo1 = xoFirst();
		XobjectEx xo2 = xoSecond();
		
		Vector<Xattr> toMerge = new Vector<Xattr>();
				
		Outer:
		for (Xattr attr2 : xo2 ) {
			if (attr2.getAsTPE() != null) {
				XattrTPE attrTPE2 = attr2.getAsTPE();
				for (Xattr attr1 : xo1 ) {
					XattrTPE attrTPE1 = attr1.getAsTPE();
					if ( attrTPE1 == null ) continue;
					if (attrTPE1.id.equals(attrTPE2.id)) continue Outer;
				}
			}
			else if (attr2.getAsSTR() != null) {
				XattrSTR attrSTR2 = attr2.getAsSTR();
				for (Xattr attr1 : xo1 ) {
					XattrSTR attrSTR1 = attr1.getAsSTR();
					if ( attrSTR1 == null ) continue;
					if ( (attrSTR1.getName().equals(attrSTR2.getName())) &&
					     (attrSTR1.getValue().equals(attrSTR2.getValue())) ) {
						continue Outer;
					}
				}
			}
			else if (attr2.getAsSTR() != null) {
				XattrURL attrURL2 = attr2.getAsURL();
				for (Xattr attr1 : xo1 ) {
					XattrURL attrURL1 = attr1.getAsURL();
					if ( attrURL1 == null ) continue;
					if ( (attrURL1.getName().equals(attrURL2.getName())) &&
					     (attrURL1.getValue().equals(attrURL2.getValue())) ) {
						continue Outer;
					}
				}
			}
			else if (attr2.getAsLNK() != null) {
				XattrLNK attrLNK2 = attr2.getAsLNK();
				XattrLNK attrLNKopo2 = attrLNK2.getOpposite();
				
				for (Xattr attr1 : xo1 ) {
					XattrLNK attrLNK1 = attr1.getAsLNK();
					if ( attrLNK1 == null ) continue;
					
					XattrLNK attrLNKopo1 = attrLNK1.getOpposite();
					
					if ( (attrLNK1.getName().equals(attrLNK2.getName())) &&
					     (attrLNKopo1.getParent() == attrLNKopo2.getParent()) &&
					     (attrLNKopo1.getName().equals(attrLNKopo2.getName())) ) {
						continue Outer;
					}
				}
			}
			
			toMerge.add(attr2);
		}
		
		for (Xattr attr : toMerge) {
			if (attr.getAsTPE() != null) {
				XattrTPE attrTPE = attr.getAsTPE();
				xo1.attrAdd(new XattrTPE(attrTPE.id));
				
			}
			else if (attr.getAsSTR() != null) {
				XattrSTR attrSTR = attr.getAsSTR();
				xo1.attrAdd(new XattrSTR(attrSTR.getName(), attrSTR.getValue()));
			}
			else if (attr.getAsURL() != null) {
				XattrURL attrURL = attr.getAsURL();
				xo1.attrAdd(new XattrSTR(attrURL.getName(), attrURL.getValue()));
			}
			else if (attr.getAsLNK() != null) {
				XattrLNK attrLNK = attr.getAsLNK();
				XattrLNK attrLNKopo = attrLNK.getOpposite();
				
				XattrLNK.connect(attrLNK.getName(), xo1, attrLNKopo.getName(), attrLNKopo.getParent());
			}
		}
		
		xo2.getDb().removeObject(xo2);
	}
	
	public void actionPerformed(ActionEvent e) {
		if ("merge".equals(e.getActionCommand())) {
			RegistrySys.registry.lock(); {
				merge();
				Selection.clean();
			} RegistrySys.registry.unlock();
			update();
		}
		else if ("clean".equals(e.getActionCommand())) {
			RegistrySys.registry.lock(); {
				Selection.clean();
			} RegistrySys.registry.unlock();	
			update();
		}
		else { //radio selection clicked
			update();
		}
	}
}
